package jp.co.nes.awssupport.access.dao;

import java.sql.Connection;
import java.sql.SQLException;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;

import jp.co.nes.awssupport.common.base.CommonException;
import jp.co.nes.awssupport.common.bean.DailyCompiledBillingBean;
import jp.co.nes.awssupport.common.dao.BaseJdbcDao;
import jp.co.nes.awssupport.common.dao.ReadType;
import jp.co.nes.awssupport.common.utility.DateUtil;
import jp.co.nes.awssupport.common.utility.DbConnUtil;

/**
 * 日次集計結果DAOです。
 */
public class DailyCompiledBillingDao extends BaseJdbcDao<DailyCompiledBillingBean> {

    /** 日次集計結果を読み込む際に使用するSelect文 */
    // max(Description)、max(Unit)については、LinkedAccountId, YearMonth, ProductName, UsageType, Rateで
    // グループ化されたものは、全て同じであるという事が、前提条件として存在する。
    private static final String READ_TOTALIZATION = ""
            + "select LinkedAccountId,"
            + "       YearMonth,"
            + "       ProductName,"
            + "       UsageType,"
            + "       min(UsageStartDate) as UsageStartDate,"
            + "       max(UsageEndDate) as UsageEndDate,"
            + "       null as ResourceId,"
            + "       null as NameTag,"
            + "       null as SpotManageFlg,"
            + "       Rate,"
            + "       sum(UsageQuantity) as UsageQuantity,"
            + "       max(Description) as Description,"
            + "       max(Unit) as Unit"
            + "  from daily_compiled_billing"
            + " where LinkedAccountId = ?"
            + "   and YearMonth = ?"
            + " group by LinkedAccountId, YearMonth, ProductName, UsageType, Rate"
            + " order by LinkedAccountId, YearMonth, ProductName, UsageType";

    /** 日次集計結果を登録する際のInsert文 */
    private static final String BATCH_INS = ""
            + "insert into daily_compiled_billing ("
            + "    UUID,"
            + "    LinkedAccountId,"
            + "    YearMonth,"
            + "    ProductName,"
            + "    UsageType,"
            + "    UsageStartDate,"
            + "    UsageEndDate,"
            + "    ResourceId,"
            + "    NameTag,"
            + "    SpotManageFlg,"
            + "    Rate,"
            + "    UsageQuantity,"
            + "    Description,"
            + "    Unit)"
            + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    /** 日次集計結果を削除する際に使用するDeletet文 */
    private static final String DEL_LINKEDACCOUNTID_YEARMONTH = ""
            + "delete from daily_compiled_billing"
            + " where LinkedAccountId = ?"
            + "   and YearMonth = ?";

    /**
     * 日次集計結果を読み込む際の区分です。
     */
    public enum DaoReadType implements ReadType {

        /** READ_TOTALIZATIONを使用して読み込む場合 */
        TOTALIZATION(READ_TOTALIZATION);

        /** Select文 */
        private String select;

        /**
         * Select文を引数にもつコンストラクタです。
         *
         * @param select Select文
         */
        private DaoReadType(String select) {
            this.select = select;
        }

        /*
         * (非 Javadoc)
         * @see jp.co.nes.awssupport.common.constant.ReadType#getSelect()
         */
        @Override
        public String getSelect() {
            return select;
        }
    }

    /**
     * デフォルトコンストラクタです。
     */
    public DailyCompiledBillingDao() {
    }

    /**
     * 引数に該当する税金適用を削除します。
     *
     * @param linkedAccountId 連結アカウントID
     * @param yearMonth 年月
     */
    public void delete(String linkedAccountId, YearMonth yearMonth) {
        try {
            Connection connection = DbConnUtil.getConn();

            Object[] params = new Object[2];
            params[0] = linkedAccountId;
            params[1] = DateUtil.toInt(yearMonth);

            QueryRunner runner = new QueryRunner();
            runner.update(connection, DEL_LINKEDACCOUNTID_YEARMONTH, params);
        } catch (SQLException e) {
            throw new CommonException(e);
        }
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.dao.BaseJdbcDao#getBatchInsQuery()
     */
    @Override
    protected String getBatchInsQuery() {
        return BATCH_INS;
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.dao.BaseJdbcDao#toConditionList(jp.co.nes.awssupport.common.constant.ReadType, java.lang.Object[])
     */
    @Override
    protected List<Object> toConditionList(ReadType readType, Object... conditions) {
        List<Object> conditionList = new ArrayList<>();
        if (readType == DaoReadType.TOTALIZATION) {
            conditionList.add(conditions[0]);
            conditionList.add(conditions[1]);
        } else {
            throw new CommonException("ReadType is wrong");
        }
        return conditionList;
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.dao.BaseJdbcDao#toBatchInsObjectList(jp.co.nes.awssupport.common.bean.BaseBean)
     */
    @Override
    protected List<Object> toBatchInsObjectList(DailyCompiledBillingBean bean) {
        List<Object> objectList = new ArrayList<>();
        objectList.add(bean.getUuid());
        objectList.add(bean.getLinkedAccountId());
        objectList.add(bean.getYearMonth());
        objectList.add(bean.getProductName());
        objectList.add(bean.getUsageType());
        objectList.add(DateUtil.toTimestamp(bean.getUsageStartDate()));
        objectList.add(DateUtil.toTimestamp(bean.getUsageEndDate()));
        objectList.add(bean.getResourceId());
        objectList.add(bean.getNameTag());
        objectList.add(bean.getSpotManageFlg());
        objectList.add(bean.getRate());
        objectList.add(bean.getUsageQuantity());
        objectList.add(bean.getDescription());
        objectList.add(bean.getUnit());
        return objectList;
    }
}
